package com.haoze.nurseapp.aop;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.haoze.common.utils.CusAccessObjectUtil;
import com.haoze.common.utils.HttpClientUtil;
import com.haoze.common.utils.UUIDUtil;
import com.haoze.nurseapp.annotation.NurseActionLog;
import com.haoze.nurseapp.dao.OperationLogMapper;
import com.haoze.nurseapp.dao.UserMapper;
import com.haoze.nurseapp.model.OperationLogEntity;
import com.haoze.nurseapp.model.UserEntity;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 护理日志切面
 */
@Component
@Aspect
public class NurseLogAop {

    private static final Logger log = LoggerFactory.getLogger(NurseLogAop.class);

    @Resource
    OperationLogMapper operationLogMapper;

    private static final ThreadLocal<String> operationLogId = new ThreadLocal<String>();
    /**
     * 切入点
     */
    @Pointcut(value = "@annotation(com.haoze.nurseapp.annotation.NurseActionLog)")
    public void entryPoint() {
        // 无需内容
    }

    @Before("entryPoint()")
    public void before(JoinPoint joinPoint) {

        log.debug("=====================开始执行前置通知==================");
        try {
            String targetName = joinPoint.getTarget().getClass().getName();

//            if (!targetName.equals("com.haoze.emr.controller.NurseFileIndexController")) {
//                return;
//            }
            String methodName = joinPoint.getSignature().getName();
            Object[] arguments = joinPoint.getArgs();
            Class<?> targetClass = Class.forName(targetName);
            Method[] methods = targetClass.getMethods();
            String operation = "";
            String nodes = "";
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    Class<?>[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length) {
                        operation = method.getAnnotation(NurseActionLog.class).value();// 操作说明
                        nodes = method.getAnnotation(NurseActionLog.class).notes(); // 是否存参标记
                        break;
                    }
                }
            }

            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String userId = request.getHeader("zuul_id");
            String requestIp = CusAccessObjectUtil.getIpAddress(request);
            String localIp = CusAccessObjectUtil.getLocalIp();
            String param = "";
            if (!nodes.equals("0")) {
                // *========控制台输出=========*//
                StringBuilder paramsBuf = new StringBuilder();
                for (Object arg : arguments) {
                    paramsBuf.append(arg);
                    paramsBuf.append("&");
                }
                log.debug("["+userId+"]执行了[" + operation + "],类:" + targetName + ",方法名：" + methodName + ",参数:"
                        + paramsBuf.toString()+",IP:"+ requestIp + ", 本地IP:" + localIp);
                param = paramsBuf.toString();
            }

            log.debug("=====================执行前置通知结束==================");

            String logId = UUIDUtil.randomString();
            operationLogId.set(logId);

            log.debug("before logId = {}", logId);
            OperationLogEntity operationLogEntity = new OperationLogEntity();
            operationLogEntity.setOperationLogId(logId);
            operationLogEntity.setGmtCreate(new Date());
            operationLogEntity.setBeginTime(new Date());
            operationLogEntity.setHospitalId("");
            operationLogEntity.setOperationUserId(userId);
            operationLogEntity.setRequestClass(targetName);
            operationLogEntity.setRequestMethod(methodName);
            operationLogEntity.setRequestParam(param);
            operationLogEntity.setRequestIp(requestIp);
            operationLogEntity.setLocalIp(localIp);
            operationLogEntity.setOperationText(operation);

            operationLogMapper.insert(operationLogEntity);

        } catch (Throwable e) {
            log.debug("around " + joinPoint + " with exception : " + e.getMessage());
        }

    }

    @After("entryPoint()")
    public void after(JoinPoint joinPoint) {

        log.debug("=====================开始执行后置通知==================");
        try {
//            String targetName = joinPoint.getTarget().getClass().getName();

//            if (!targetName.equals("com.haoze.emr.controller.NurseFileIndexController")) {
//                return;
//            }
//            String methodName = joinPoint.getSignature().getName();
//            Object[] arguments = joinPoint.getArgs();
//            Class<?> targetClass = Class.forName(targetName);
//            Method[] methods = targetClass.getMethods();
//            String operation = "";
//            String nodes = "";
//            for (Method method : methods) {
//                if (method.getName().equals(methodName)) {
//                    Class<?>[] clazzs = method.getParameterTypes();
//                    if (clazzs.length == arguments.length) {
//                        operation = method.getAnnotation(ApiOperation.class).value();// 操作说明
//                        nodes = method.getAnnotation(ApiOperation.class).notes(); // 是否存参标记
//                        break;
//                    }
//                }
//            }

//            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//            String userId = request.getHeader("zuul_id");
//            String requestIp = CusAccessObjectUtil.getIpAddress(request);
//            String localIp = CusAccessObjectUtil.getLocalIp();
//            String param = "";
//            if (!nodes.equals("0")) {
//                // *========控制台输出=========*//
//                StringBuilder paramsBuf = new StringBuilder();
//                for (Object arg : arguments) {
//                    paramsBuf.append(arg);
//                    paramsBuf.append("&");
//                }
//                log.debug("["+userId+"]执行了[" + operation + "],类:" + targetName + ",方法名：" + methodName + ",参数:"
//                        + paramsBuf.toString()+",IP:"+ requestIp + ", 本地IP:" + localIp);
//                param = paramsBuf.toString();
//            }

            log.debug("=====================执行后置通知结束==================");


            String logId = operationLogId.get();
            log.debug("after logId = {}", logId);
            OperationLogEntity operationLogEntity = new OperationLogEntity();
            operationLogEntity.setOperationLogId(logId);
            operationLogEntity.setEndTime(new Date());
            operationLogMapper.updateByPrimaryKeySelective(operationLogEntity);

        } catch (Throwable e) {
            log.debug("around " + joinPoint + " with exception : " + e.getMessage());
        }

    }
    /**
     * 环绕通知处理处理
     *
     * @param point
     * @throws Throwable
     */
    @Around("entryPoint()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 先执行业务,注意:业务这样写业务发生异常不会拦截日志。
        Object result = point.proceed();
        log.debug("=====around=====");
        try {
            handleAround(point);// 处理日志
        } catch (Exception e) {
            log.error("日志记录异常", e);
        }
        return result;
    }

    /**
     * around日志记录
     *
     * @param point
     * @throws SecurityException
     * @throws NoSuchMethodException
     */
    public void handleAround(ProceedingJoinPoint point) throws Exception {

//        Object target = point.getTarget();
//        String targetName = target.getClass().getName();
//
//        if (!targetName.equals("com.haoze.emr.controller.NurseFileIndexController")) {
//            return;
//        }

        log.debug("handleAround");
//        Signature sig = point.getSignature();
//        MethodSignature msig = null;
//        if (!(sig instanceof MethodSignature)) {
//            throw new IllegalArgumentException("该注解只能用于方法");
//        }
//        msig = (MethodSignature) sig;
//
//        Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
//        // 方法名称
//        String methodName = currentMethod.getName();
//        // 获取注解对象
//        ApiOperation aLog = currentMethod.getAnnotation(ApiOperation.class);
//        // 类名
//        String className = point.getTarget().getClass().getName();
//        // 方法的参数
//        Object[] params = point.getArgs();
//
//        StringBuilder paramsBuf = new StringBuilder();
//        for (Object arg : params) {
//            paramsBuf.append(arg);
//            paramsBuf.append("&");
//        }
//        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//        String userId = request.getHeader("zuul_id");
//        String requestIp = CusAccessObjectUtil.getIpAddress(request);
//        String localIp = CusAccessObjectUtil.getLocalIp();
//        // 处理log。。。。
//        log.debug("["+userId+"]执行了[" + aLog.value() + "],类:" + className + ",方法名：" + methodName + ",参数:"
//                + paramsBuf.toString()+",IP:"+requestIp + ", 本地IP:" + localIp);

    }

    @AfterThrowing(pointcut = "entryPoint()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
        // 通过request获取登陆用户信息
//         HttpServletRequest request = ((ServletRequestAttributes)
//         RequestContextHolder.getRequestAttributes()).getRequest();
        log.debug("doAfterThrowing");
//        try {
//            String targetName = joinPoint.getTarget().getClass().getName();
//
//            if (!targetName.equals("com.haoze.emr.controller.NurseFileIndexController")) {
//                return;
//            }
//
//            String className = joinPoint.getTarget().getClass().getName();
//            String methodName = joinPoint.getSignature().getName();
//            Object[] arguments = joinPoint.getArgs();
//            Class<?> targetClass = Class.forName(targetName);
//            Method[] methods = targetClass.getMethods();
//            String operation = "";
//            for (Method method : methods) {
//                if (method.getName().equals(methodName)) {
//                    Class<?>[] clazzs = method.getParameterTypes();
//                    if (clazzs.length == arguments.length) {
//                        operation = method.getAnnotation(ApiOperation.class).value();
//                        break;
//                    }
//                }
//            }
//
//            StringBuilder paramsBuf = new StringBuilder();
//            for (Object arg : arguments) {
//                paramsBuf.append(arg);
//                paramsBuf.append("&");
//            }
//
//            log.debug("异常方法:" + className + "." + methodName + "();参数:" + paramsBuf.toString() + ",处理了:" + operation);
//            log.debug("异常信息:" + e.getMessage());
//        } catch (Exception ex) {
//            log.error("异常信息:{}", ex.getMessage());
//        }
    }


    @Resource
    UserMapper userMapper;
    @Value("${spring.profiles.active}")
    private String activeProfile;
    /**
     * 切入点
     */
    @AfterReturning(value = "execution(* com.haoze.nurseapp.controller.LabQrCodeController.finish(..))", returning = "result")
    public void afterReturningMethod(JoinPoint point, Object result) {
        try {
            if ("prod".equals(activeProfile)) {
                String userId = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("zuul_id");
                UserEntity user = userMapper.queryUserId(userId);
                Object[] args = point.getArgs();
                List<String> list = (List<String>) args[0];
                List<Map<String, String>> resultList = list.stream().map(str -> {
                    Map<String, String> map = new HashMap<>(2);
                    map.put("BarCode", str);
                    map.put("Changer", user.getUserName());
                    return map;
                }).collect(Collectors.toList());
                Map<String, Object> finalResult = new HashMap<>(2);
                finalResult.put("BarcodeInfo", resultList);
                log.info("lis更新采集时间入参{}", JSON.toJSONString(finalResult));
                JSONObject jsonObject = HttpClientUtil.sendPost("http://172.20.91.75:4003/lisapi/getLisChangeBarcode", finalResult);
                log.info("lis更新采集时间出参{}", jsonObject);
            }
        } catch (Exception e) {
            log.error("lis更新采集时间出错", e);
        }
    }
}
